<?php

/**
 * 
 * \file luminous_common_grammars.php
 * \brief Grammar definitions (and examples) for common languages
 * 
 * \example luminous_common_grammars.php 
 * Built in grammar definitions, browse these to get a feel for how to write
 *      your own.
 * 
 * \todo clean up regex rules with proper char classes.
 * \todo arrange the regex rules according to \ref grammar_optimisation
 * 
 */

 
require_once('luminous_grammar.class.php');


function luminous_generic_comment($delim1 = "//", $delim2 = "\n",
$callback='luminous_type_callback_comment')
{
  return new LuminousDelimiterRule(0, 'COMMENT', 0, $delim1, $delim2, 
    $callback);
}

function luminous_generic_doc_comment($delim1 = "///", $delim2 = "\n")
{
  return new LuminousDelimiterRule(0, 'DOCCOMMENT', 0, $delim1, $delim2,
  'luminous_type_callback_doccomment');
}

function luminous_generic_string($delim1 = '"', $delim2 = '"',
  $callback = 'luminous_type_callback_generic_string')
{
  return new LuminousDelimiterRule(0, 'STRING', 0, $delim1, $delim2, $callback);
}

function luminous_generic_sql_string($delimiter = "'")
{
  $regex = "/
  $delimiter{2}|
  $delimiter
  .*?
  (?<!$delimiter)
  $delimiter
  (?!$delimiter)
  /sx";
  
  return new LuminousDelimiterRule(0, 'STRING', LUMINOUS_COMPLETE|LUMINOUS_REGEX,
  $regex, null, 'luminous_type_callback_sql_single_quotes');
}

function luminous_generic_regex($modifiers, 
$callback = 'luminous_type_callback_generic_regex',
  $preceding_chars = "[\(\[,=:;\?!\|\&~]")
{
  $regex = 
  "/
  (?<=($preceding_chars))
  
  [\s]* 
  \/(?![\/\*])
  (?:.*?[^\\\])*?
  (?:\\\\\\\\)*\/
  [$modifiers]*/sx";
  
  return new LuminousDelimiterRule(0, 'REGEX', LUMINOUS_REGEX|LUMINOUS_COMPLETE,
  $regex, null, $callback);
}

function luminous_generic_shebang($identifier='#!', $end="\n")
{
  return new LuminousDelimiterRule(0, 'SHEBANG', 
    LUMINOUS_REGEX|LUMINOUS_COMPLETE, "/^[\s]*$identifier.*?$end/");
}

function luminous_generic_constant()
{
  return new LuminousSimpleRule(3, 'CONSTANT', LUMINOUS_REGEX,
    '/(?<![[:alnum:]_&<])\b[A-Z_][A-Z0-9_]{2,}(?![[:alnum:]_])/');
}

function luminous_generic_generics()
{
}


/**
 * \return a generic regex literal regex rule
 */ 
function luminous_generic_regex_literal($modifiers, 
  $preceding_chars = "[
                        \(\[,=:;\?!\|\&~
                      ]")
{
  return "/
  (?<=($preceding_chars))
  [\s]* 
  \/(?![\/\*])
  (?:.*?[^\\\])*?
  (?:\\\\\\\\)*\/
  [$modifiers]*/x";
}

/**
 * \return a generic string literal regex, where it uses doubling of
 * delimiters to escape.
 */ 
function luminous_generic_str_literal_sql($delimiter='\'')
{
  return 
  "/
  (?:$delimiter$delimiter)
  |
  (?:(?:$delimiter.*?(?<!$delimiter)$delimiter)(?!$delimiter))
  /sx";
}

/// \cond 




// no point generating class docs for all of these.


/* I don't actually know ActionScript so there's definitely room for improvement
 * in this one
 */
class LuminousGrammarActionscript extends LuminousGrammar
{
  public $keywords = array('as',
  'break',
  'case|catch|class|const|continue',  
  'default|delete|do',
  'else|extends',
  'false|finally|for|function',
  'if|impements|import|in|instanceof|interface|internal|is',
  'native|new|null',
  'package|private|protected|public',
  'return',
  'super|switch',
  'this|throw|to|true|try|typeof',
  'use',
  'void',
  'while|with',  
  );
  
  public $types = array('String', 'var');
  public $oo_separators = array('\.');
  function __construct()
  {
    $this->delimited_types = array(
      luminous_generic_doc_comment('/**', '*/'),
      luminous_generic_comment('//'),
      luminous_generic_comment('/*', '*/'),
      luminous_generic_string('"', '"'),
      luminous_generic_string("'", "'"),
      luminous_generic_regex('gimsx')
    );
    
    $this->SetInfoLanguage("as");
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoVersion('0.25.00');          
    $this->SetSimpleTypeRules();
    $this->simple_types[] = luminous_generic_constant();
  }
}


class LuminousGrammarActionscriptEmbedded extends LuminousGrammarActionscript
{
  public function __construct()
  {
    parent::__construct();
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoVersion('0.25.00');
    
    $this->simple_types = array_merge( 
      array(
        new LuminousSimpleRule(0, 'COMMENT', LUMINOUS_REGEX,
        '/(?:&lt;!\[CDATA\[)|(?:\]\]&gt;)/')
        ),
        $this->simple_types
        );
    
    $this->ignore_outside = array(
      new LuminousBoundaryRule(LUMINOUS_REGEX|LUMINOUS_EXCLUDE, 
      '/&lt;[\s]*mx:Script[\s]*&gt;/i',
      '/&lt;[\s]*\/[\s]*mx:Script[\s]*&gt;/i')
      );
      
     $this->child_grammar = new LuminousGrammarHTML();
  }
  
}


class LuminousGrammarChangelog extends LuminousGrammar
{
  public function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
          'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('changelog');
    $this->SetInfoVersion('0.25.00');
    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule(3, 'VALUE', LUMINOUS_REGEX,
      '/^[ \t]+[*\-\+][ \t]/m', "/$|(?=\n[ \t]*\n)/"
      )
    );
      
    
    $this->simple_types = array(
      // Changelog heading
      new LuminousSimpleRule(0, 'KEYWORD', LUMINOUS_REGEX,
        "/^[a-zA-Z0-9_].*$/m"),
      // --
      new LuminousSimpleRule(0, 'COMMENT', LUMINOUS_REGEX,
        "/^[\s]*\-\-(?!\-).*$/m"),
      // subheading, if present
      new LuminousSimpleRule(1, 'TYPE', LUMINOUS_REGEX,
        '/^[\s]+.*:[ \t]*$/m')
//       new LuminousSimpleRule(2, 'VALUE', LUMINOUS_REGEX,
//         "/(^|\n)[ \t]+(?:\*|(?:-(?!-)))[ \t].*?($|(?=(\n\n)))/s")
      
    );
  }
  
}


class LuminousGrammarCpp extends LuminousGrammar
{    
  public $keywords = array('asm|auto', 'break', 
    'case|catch|class|continue|const(?:_cast)?', 
    'default|delete|do|dynamic_cast', 'else|explicit|extern', 'for|friend', 
    'goto', 'if|inline', 'mutable', 'namespace|new', 'operator', 
    'private|protected|public', 'register|reinterpret_cast|return', 
    'static(?:_cast)?|switch', 'template|this|throw|try|typedef|typeid|typename', 
    'union|using', 'virtual|volatile', 'while');
  
  public $types =  array('FALSE', 'NULL', 'TRUE', 'bool', 'char', 'double', 
  'enum', 'false|float', 'int', 'long', 'short|signed|struct', 'true', 
  'union|unsigned', 'void', 'wchar_t');
    
  public $oo_separators = array('\.', '-&gt;');


  public $functions = array('sizeof', 'malloc', 'free');
  
  public function __construct()
  {
    $this->SetInfoAuthor( 
      array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
        'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('cpp');
    $this->SetInfoVersion('0.25.00');
    
    
    $this->delimited_types = array(
      luminous_generic_doc_comment('/**', '*/'),
      luminous_generic_doc_comment('/*!', '*/'),
      luminous_generic_doc_comment('//!', "\n"),
      luminous_generic_doc_comment('///', "\n"),
      
      luminous_generic_comment('/*', '*/'),
      luminous_generic_comment('//', "\n"),
      luminous_generic_comment('#if 0', "#endif"),
      
      luminous_generic_string('"', '"'),
      
      new LuminousDelimiterRule(0, 'CHARACTER', 0, '\'', '\'',
        'luminous_type_callback_cstring'),
      new LuminousDelimiterRule(0, 'PREPROCESSOR', 0, '#', "\n")
    ); 
    
    $this->SetSimpleTypeRules();
    $this->simple_types[] = luminous_generic_constant();
  }
}





// TODO this
class LuminousGrammarGeneric extends LuminousGrammar
{
  
  
}


class LuminousGrammarLatex extends LuminousGrammar
{
  
  public $type_regex = "/\\\(%TYPE)/";
  public $types = array('alpha', 'theta', 'tau', 
  'beta', 'vartheta', 'pi', 'upsilon', 
  'gamma', 'gamma', 'varpi', 'phi', 
  'delta', 'kappa', 'rho', 'varphi', 
  'epsilon', 'lambda', 'varrho', 'chi', 
  'varepsilon', 'mu', 'sigma', 'psi',
  'zeta', 'nu', 'varsigma', 'omega', 
  'eta', 'xi', 
  'Gamma', 'Lambda', 'Sigma', 'Psi',
  'Delta', 'Xi', 'Upsilon', 'Omega', 
  'Theta', 'Pi', 'Phi');
  

  
  public $operators = array();
  
  public $numeric_regex = null;
  
  public function __construct()
  {
    $this->SetInfoLanguage('latex');
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoVersion('0.25.00');
    
    $this->delimited_types = array(
      new LuminousDelimiterRule(0, 'COMMENT', LUMINOUS_REGEX|LUMINOUS_COMPLETE, 
        '/(?<!\\\)%.*?$/m'),
        
      // this definitely shouldn't be variable, it's the range of a 
      // square bracket, but not nested ones
      new LuminousDelimiterRule(3, 'VARIABLE', LUMINOUS_REGEX|LUMINOUS_COMPLETE,
        '/(?<=[^\\\]\[)(?:[^\[\\\]+?)(?=(\]))/', null, null),
      
      // Curley brace
      new LuminousDelimiterRule(3, 'VALUE', LUMINOUS_REGEX|LUMINOUS_COMPLETE,
        '/(?<=[^\\\]\{)(?:[^\{\\\]+?)(?=(\}))/', null, null)
     );
     


    $this->SetSimpleTypeRules();
    
    $keyword_regex = "/\\\(%KEYWORD)/";
    
    // I'm trying to keep this more oriented towards common layout and 
    // formatting commands, not all the maths stuff, will be caught by the 
    // general rule.
    // But I haven't used LaTeX much, and when I did it was always for maths
    // (the irony).
    $keywords = array('@', 'begin', 'DisableLigatures', 'end', 'emph', 
      'fbox', 'footnotesize', 'frenchspacing', '[hH]uge', 'hyphonation', 
      '[lL]arge', 'LARGE', 'ldots', 'mathrm', 'mbox', 'newcommand', 'normalem', 
      'normalsize', 'oldstylenums', 'scriptsize', 'small', 'sout', 'tiny', 
      'text(normal|rm|sf|tt|up|it|sl|sc|bf|md|(super|sub)script|color)', 
      'ulem', 'underline', 'usepackage', 'uwave');
  
    $this->simple_types[] = new LuminousSimpleRuleList(2, 'LATEX_FUNCTION',
      LUMINOUS_REGEX, $keywords, $keyword_regex, '%KEYWORD');
    

    
    
    // kind of a generic thing to catch everything else.
    $this->simple_types[] = 
      new LuminousSimpleRule(3, 'FUNCTION', LUMINOUS_REGEX, 
        '/
          (?:\\\)
          (?:
            (?:[[:alnum:]]+)
            | [\-\\\\{\}%]
            
            )
            
        /x');
        
    $this->simple_types[] = new LuminousSimpleRuleList(4, 'LATEX_OPERATOR', 
      LUMINOUS_REGEX, array('\[', '\]', '\{', '\}'), '/(%OP)+/', '%OP');
  }
  
}



/// \todo this could do with some work, but I don't know Pascal.
class LuminousGrammarPascal extends LuminousGrammar

{
  public $case_insensitive = true;
  
  public $operators = array('(?<![a-zA-Z0-9_])and(?![a-zA-Z0-9_])', 
  '(?<![a-zA-Z0-9_])div(?![a-zA-Z0-9_])', 
    '(?<![a-zA-Z0-9_])in(?![a-zA-Z0-9_])',    
    
    '(?<![a-zA-Z0-9_])sh[lr](?![a-zA-Z0-9_])',        
    '(?<![a-zA-Z0-9_])not(?![a-zA-Z0-9_])',  
    '(?<![a-zA-Z0-9_])or(?![a-zA-Z0-9_])',
    '(?<![a-zA-Z0-9_])mod(?![a-zA-Z0-9_])',
    
    '(?<![a-zA-Z0-9_])xor(?![a-zA-Z0-9_])',
    
    '\+', '\*', '-', '\/', '=', '&[gl]t;', '=','!', '%', '&amp;', '\|','~',
    '\^', '\[', '\]');
    
  public $keywords = array(
    'absolute|abstract|all|and_then|array|as|asm',
    'begin|bindable',
    'case|class|const|constructor',
    'destructor|dispose|do|downto',
    'else|end|except|exit|export|exports',
    'false|file|finalization|finally|for|function',
    'goto',
    'if|implementation|import|inherited|initialization|inline|interface|is',
    'label|library',
    'module',
    'new|nil',
    'object|of|on|only|operator|or_else|otherwise',
    'packed|pow|procedure|program|property|protected',
    'qualified',
    'raise|record|repeat|restricted',
    'set',
    'then|threadvar|to|true|try|type',
    'unit|until|uses',
    'value|var|view|virtual',
    'while|with',
    'xor');   
  
  
  public $types = array(
    'Integer',
    'Shortint',
    'SmallInt',
    'Longint',
    'Longword',
    'Int64',
    'Byte',
    'Word',
    'Cardinal',
    'QWord',
    'Boolean',
    'ByteBool',
    'WordBool',
    'LongBool',
    'Char');
    
  
  public function __construct()
  {
    $this->SetInfoLanguage('pascal');
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoVersion('0.25.00');          
    
    $this->delimited_types = array(
      luminous_generic_comment('{', '}'),
      luminous_generic_comment('(*', '*)'),
      luminous_generic_comment('//', "\n"),
      
      luminous_generic_sql_string("'"),
      luminous_generic_sql_string('"')
    );
    
    $this->SetSimpleTypeRules();
    
  }
  
  
  
}


class LuminousGrammarPython extends LuminousGrammar
{
  public $operators = array('(?<![a-zA-Z0-9_])and(?![a-zA-Z0-9_])', 
    '(?<![a-zA-Z0-9_])not(?![a-zA-Z0-9_])', 
    '(?<![a-zA-Z0-9_])i[ns](?![a-zA-Z0-9_])',    
    '(?<![a-zA-Z0-9_])or(?![a-zA-Z0-9_])',
    '\+', '\*', '-', '\/', '=', '&[gl]t;', '=','!', '%', '&amp;', '\|','~',
    '\^', '\[', '\]');
    
  public $keywords = array('del', 'for', 'raise', 'assert', 'elif', 'from', 
    'lambda', 'return', 'break', 'else', 'global', 'try', 'class', 'except', 
    'if', 'while','continue', 'exec', 'import', 'pass', 'yield', 'def', 
    'finally', 'print', 'as');
  
  // okay so these aren't really types but it makes it more colourful.
  public $types = array('False', 'True', 'None',
    'self',
    'int', 'float', 'long', 'complex',
    'str', 'unicode', 'list', 'tuple', 'buffer',
    'set', 'frozenset', 'dict',
    'memoryview',
    'Ellipsis',
  );
  
  public $functions = array('len', 'x?range');
  public $oo_separators = array('\.');
    
  public $numeric_regex = '
    /(?<![a-zA-Z_0-9<])  
    (?:
      #hex 
      (?:0[xX][0-9A-Fa-f]+)
    |
      (?:0[bB][0-1]+)
    |
      (?:0[oO0][0-8]+)      
    | 
      # regular number
      (?:
        [0-9]+
        (?:
          # fraction
          \.(?:[0-9]+(?:[eE]?[0-9]+)?)
        )?
      )
      |
      (?:
        # or only after the point
        \.(?:[0-9]+(?:[eE]?[0-9]+)?)
      )
    )
    [jJlL]?
    /x';
    
  public function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
          'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('py');
    $this->SetInfoVersion('0.25.00');    
    
    $this->delimited_types = array(
      luminous_generic_shebang(),
      luminous_generic_comment("#", "\n"),
      luminous_generic_doc_comment("'''", "'''"),
      luminous_generic_doc_comment('"""', '"""'),
      
      new LuminousDelimiterRule(0, 'STRING', LUMINOUS_REGEX, 
      '/[ruRU]{0,2}\'/', '/\'/', 'luminous_type_callback_pystring'),
      
      new LuminousDelimiterRule(0, 'STRING', LUMINOUS_REGEX, 
      '/[ruRU]{0,2}"/', '/"/', 'luminous_type_callback_pystring')    
      );
      

    
    $this->SetSimpleTypeRules();
    $this->simple_types[] = luminous_generic_constant();
    
  }
}

class LuminousGrammarRuby extends LuminousGrammar
{
  public $operators =  array('(?<![a-zA-Z0-9])and(?![a-zA-Z0-9])', 
    '(?<![a-zA-Z0-9])not(?![a-zA-Z0-9])', '(?<![a-zA-Z0-9])in(?![a-zA-Z0-9])', 
    '(?<![a-zA-Z0-9])or(?![a-zA-Z0-9])', '\+', '\*', '-', '\/', '=',  '&gt;', 
    '&lt;', '=','!', '%', '&amp;', '\|', '~', '\^', '\[', '\]');
    
  public $keywords =  array("alias", "BEGIN", "(?<!=)begin", "break", "case",
    "class", "def","defined", "do", "else", "elsif", "END", "(?<!=)end", 
    "ensure", "false", "for", "if", "module", "next", "nil", "redo", "rescue", 
    "retry", "return", "self", "super", "then", "true", "undef", "unless",
    "until", "when", "while", "yield");
    
    public $types = array('false', 'nil', 'true');
      
  public $oo_separators = array('\.');
  public function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('rb');
    $this->SetInfoVersion('0.25.00');        
        
    
    $this->delimited_types = array(
      new LuminousDelimiterRule(0, "DOCCOMMENT", 
        LUMINOUS_REGEX|LUMINOUS_COMPLETE, "/^=begin(?:.*?)^=end/ms"),
      luminous_generic_comment("#", "\n"),
      
      luminous_generic_string("'", "'", 
        'luminous_type_callback_php_sstring'),
      luminous_generic_string('"', '"',
      'luminous_type_callback_cstring'),
        
      new LuminousDelimiterRule(0, "STRING", 
        LUMINOUS_DYNAMIC_DELIMS|LUMINOUS_COMPLETE|LUMINOUS_EXCLUDE, "%w"),
        
      new LuminousDelimiterRule(0, "REGEX", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
          '/
      (?<=([\(\[,=:;\?!~]))
      [\s]* 
      \/
        (?:.*?[^\\\])*?
        (?:\\\\\\\\)*\/
      [iomx]*/x',
      null,
      'luminous_type_callback_generic_string'
      ),
      
      new LuminousDelimiterRule(0, "REGEX", LUMINOUS_REGEX|LUMINOUS_DYNAMIC_DELIMS,
      '/%r[\s]*/s', '[iomx]*/', 'luminous_type_callback_generic_string'),
      
      new LuminousDelimiterRule(0, 'HEREDOC', 
        LUMINOUS_REGEX|LUMINOUS_DYNAMIC_DELIMS|LUMINOUS_COMPLETE,
        "/&lt;&lt;(?:\-)?(.*&lt;&lt;(?:\-)?)?(?![\s])/")
    );
    $this->simple_types[] = new LuminousSimpleRule(3, 'VARIABLE',
      LUMINOUS_REGEX, "/(?!<[a-z0-9_])(?:@@?|\\$)[a-z0-9_]+/i");

    $this->SetSimpleTypeRules();
    $this->simple_types[] = luminous_generic_constant();
    
  }
}

class LuminousGrammarRubyHTML extends LuminousGrammarRuby
{
  
  public function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('rhtml');
    $this->SetInfoVersion('0.25.00');
    
    $this->child_grammar = new LuminousGrammarJavaScriptEmbedded();
    $this->ignore_outside = array(
      new LuminousBoundaryRule(LUMINOUS_REGEX,
      "/&lt;%=?/", "/%&gt;/")
    
    );
    $this->keywords[] = "&lt;%=?";
    $this->keywords[] = "%&gt;";
    parent::__construct();
    
  }
}



class LuminousGrammarHTMLText extends LuminousGrammar
{  
  function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('htmltext');
    $this->SetInfoVersion('0.25.00');        
    
    $this->simple_types = array(
      new LuminousSimpleRule(4, 'ESC', LUMINOUS_REGEX, 
      "/(?:&amp;)(?:[a-z]+|(#[0-9]+));/i")
      );
  }  
}


class LuminousGrammarHTML extends LuminousGrammar
{
 function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('html');
    $this->SetInfoVersion('0.25.00');        
    
    $this->ignore_outside = array( 
    new LuminousBoundaryRule(0, "&lt;", "&gt;")
    );
    $this->child_grammar = new LuminousGrammarHTMLText();
    
    $test = true;
    
    $this->delimited_types = array(    
    new LuminousDelimiterRule(0, "COMMENT", LUMINOUS_END_IS_END,
    "&lt;!--", "--&gt;"),    
      new LuminousDelimiterRule(0, "COMMENT", LUMINOUS_END_IS_END,
      "&lt;!", "&gt;")
    );

    $this->delimited_types[] = new LuminousDelimiterRule(0, "STRING", 
      LUMINOUS_REGEX|LUMINOUS_COMPLETE,
      "/
        (?:'')
        |
        (?:'.*?(?:'|(?=&[lg]t;)))
      /xs");
    
    $this->delimited_types[] = new LuminousDelimiterRule(0, "STRING", 
    LUMINOUS_REGEX|LUMINOUS_COMPLETE,
    '/
    (?:"")|
    (?:".*?(?:"|(?=&gt;)))
    /xs');  
   

    $this->simple_types = array();      
      
    $this->simple_types[] = new LuminousSimpleRule(2, "TYPE", LUMINOUS_REGEX,
    "/(?<=([\s]))(?:[a-z\-:]+)(?=([=]))/i");
    $this->simple_types[] = new LuminousSimpleRule(1, "HTMLTAG", LUMINOUS_REGEX,
    "/(?<=(&lt;))(!?|\/?)[a-z0-9_\-\:]+/i");
    $this->simple_types[] = new LuminousSimpleRule(2, 'VALUE', LUMINOUS_REGEX,
    "/(?<=(=))[\s]*[^\s]+/");
  }
}

class LuminousGrammarCSS extends LuminousGrammar
{


  function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('css');
    $this->SetInfoVersion('0.25.00');        
    
    $this->delimited_types = array(
      luminous_generic_comment('/*', '*/'),
      luminous_generic_string("'", "'"),
      luminous_generic_string("\"", "\"")
      );
      
    $this->simple_types = array(
      new LuminousSimpleRule(3, 'KEYWORD', LUMINOUS_REGEX,
      "/(?<=^|\}|>)([\s]*)([a-z0-9_\- \t\.#:,]*)([\s]*\{)/si", null, 2),
      
      new LuminousSimpleRule(2, "TYPE", LUMINOUS_REGEX, 
      "/[a-zA-Z\-]+[\s]*(?=[:])/"),
      new LuminousSimpleRule(2, "VALUE", LUMINOUS_REGEX, 
        "/(?<=[:])[\s]*.+?(?=[;\}$])/s"),

      
      new LuminousSimpleRuleList(4, "OPERATOR", 0, 
        array(';', ':', '#', '.', '{', '}'))
      );
  }
}


class LuminousGrammarCSSEmbedded extends LuminousGrammarCSS
{

  function __construct()
  {
    $this->ignore_outside = array(
      new LuminousBoundaryRule(LUMINOUS_REGEX|LUMINOUS_EXCLUDE, 
      "/(&lt;style.*?&gt;)/si", "/(&lt;\/style&gt;)/si")
      );
    $this->child_grammar = new LuminousGrammarHTML();
   
    parent::__construct();
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoVersion('0.25.00');          
  }
}

class LuminousGrammarJavaScript extends LuminousGrammar
{


//     public $keywords =  array("break",  "case", "catch", "comment", "continue", "delete", "do", "default", "else", "export", 
//   "for", "function",  "if", "import", "in",   "label", "new",  "return",  "switch",  "try",  "void","while", "with");
  
//   public $keywords =  array("break", "c(?:a(?:se|tch)|o(?:mment|ntinue))", "d(?:e(?:fault|lete)|o)", "e(?:lse|xport)",
//     "f(?:or|unction)", "i(?:f|mport|n)",   "label", "new",  "return",  "switch",  "try",  "void", "w(?:hile|ith)");   

public $keywords =  array("break", "c(ase|atch|omment|ontinue)", "d(efault|elete|o)", "e(lse|xport)",
  "f(or|unction)", "i(f|mport|n)",   "label", "new",  "return",  "switch",  "try",  "void", "w(hile|ith)");    
  
  public $functions = array('typeof');
  public $types = array('this', 'var');
  
//   public $operators = array();
  public $oo_separators = array('\.');

  public function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('js');
    $this->SetInfoVersion('0.25.00');    
    
    
    $this->delimited_types = array(
      luminous_generic_doc_comment('/**', '*/'),
      luminous_generic_doc_comment('/*!', '*/'),
      luminous_generic_doc_comment('//!', "\n"),
      luminous_generic_doc_comment('///', "\n"),
      
      luminous_generic_comment('/*', '*/'),                               
      new LuminousDelimiterRule(0, 'COMMENT', LUMINOUS_STOP_AT_END, '//', "\n"),
      luminous_generic_string('"', '"'),
      luminous_generic_string("'", "'"),
      luminous_generic_regex('igm')
      
      // I can't decide which is faster.
      
// //       new LuminousDelimiterRule("REGEX", LUMINOUS_REGEX,
// //         '/
// //           (?<=([\(\[,=:;\?!]))
// //           [\s]* 
// //           \/[^\/\*]
// //           /x', '/\/[igm]*/')
//       
//       new LuminousDelimiterRule("REGEX", LUMINOUS_REGEX|LUMINOUS_COMPLETE, 
//         '/
//         (?<=([\(\[,=:;\?!\|\&]))
//         [\s]* 
//         \/(?![\/\*])
//         (?:.*?[^\\\])*?
//         (?:\\\\\\\\)*\/
//         [igm]*/x',
//         null,
//         'luminous_type_callback_generic_string'
//       )
    );


    $this->SetSimpleTypeRules();
    $this->simple_types[] = luminous_generic_constant();
    
  }
  
  
}


class LuminousGrammarJavaScriptEmbedded extends LuminousGrammarJavaScript
{

  function __construct()
  {    
    $this->ignore_outside = array(
      new LuminousBoundaryRule(LUMINOUS_REGEX|LUMINOUS_EXCLUDE,
      "/(?:&lt;script.*?&gt;)/si", "/(?:&lt;\/?script&gt;)/si")
      );    
    $this->child_grammar = new LuminousGrammarCSSEmbedded();
    
    parent::__construct();
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoVersion('0.25.00');          
    
  }
}



class LuminousGrammarBash extends LuminousGrammar
{
  
  function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('sh');
    $this->SetInfoVersion('0.25.00');        
    
    $this->keyword_regex = '/(?<![a-zA-Z0-9_$\.])(?:%KEYWORD)(?![a-zA-Z0-9_\.])/';
    
    
    $this->numeric_regex = '
    /(?<![[:alnum:]_<$\.\-])  
    (
      #hex 
      (?:0[xX][0-9A-Fa-f]+)
    |
      # regular number
      (?:
        [0-9]+
        (?:
          # fraction
          \.[0-9]+([eE]?[0-9]+)?
        )?
      )
      |
      (?:
        # or only after the point, float x = .1;
        \.[0-9]+(?:[eE]?[0-9]+)?
      )
    )
    (?![[:alnum:]_<$\.\-]) 
    /x';
    
    
    $this->keywords = array_merge($this->keywords, 
      array("case", "do", "done", "elif", "else", "esac", "fi", "for",
    "function", "if", "in", "select", "then", "time", "until", "while")
    );
    
    $this->operators = array();
    
    // just some common ones or I'll be here all year.
    $this->functions = array("awk", "cat", 'cd', "chmod", "chown", "cp", "cut", 
      "date", "diff", "echo", "egrep", "env", "eval", "exit", "export", "file",
      "find", "ftp", "gawk", "grep", "gzip", "head", "help", 'join', 'less', 
      'ln', 'ls', 'mkdir', 'mv', 'ps', 'pwd', 'read', 'rename', 'rm', 'rmdir', 
      'sed', 'sleep', 'sort', 'ssh', 'sudo', 'su', 'tail', 'tar', 'time',
      'touch'); 
    
    $this->delimited_types = array(
      luminous_generic_shebang(),
      new LuminousDelimiterRule(0, 'COMMENT', LUMINOUS_REGEX|LUMINOUS_COMPLETE,
      '/(?<!\$)#.*$/m'),
      luminous_generic_string('"', '"', 'luminous_type_callback_bash_string'),
      luminous_generic_string("'", "'", 'luminous_type_callback_bash_string'),

      //obviously these are function calls, but it looks prettier if they're not.
      // and it's easier to read. Perhaps need a new identifier.
      new LuminousDelimiterRule(0, "TYPE", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
      '/\$\([^\(]+\)/', null, 'luminous_type_callback_bash_string'),
      
      new LuminousDelimiterRule(0, 'FUNCTION', 0, '`', '`',
        'luminous_type_callback_bash_string'),
        
      new LuminousDelimiterRule(0, 'HEREDOC', 
        LUMINOUS_COMPLETE|LUMINOUS_DYNAMIC_DELIMS|LUMINOUS_REGEX, 
        '/(?:&lt;){2}[\-\\\]?/')
      );
      
    $this->simple_types[] =     
      new LuminousSimpleRule(3, "VARIABLE", LUMINOUS_REGEX,
        '/[[:alnum:]_-]*?[\s]*(?=[=])/m');
    $this->simple_types[] =     
        new LuminousSimpleRule(3, "VARIABLE", LUMINOUS_REGEX,
        '/\${.*?}/m');
        
    $this->simple_types[] =         
      new LuminousSimpleRule(3, 'VARIABLE', LUMINOUS_REGEX,
        "/\\$(?:(?:[[:alnum:]_-]+)|[#\*\?])/");
        
    // yes this again. ./
    $this->simple_types[] = 
      new LuminousSimpleRule(2, 'TYPE', LUMINOUS_REGEX, 
        '/(?<![[:alnum:]_\$\.])\.\/.*?[^\s]([\s]|$)/');
         
    $this->SetSimpleTypeRules();
  }
}

class LuminousGrammarMakefile extends LuminousGrammarBash
{
  function __construct()
  {
    
    $this->keywords[] = "endif";
    $this->keywords[] = "ifdef";
    
    // dependency
    $this->simple_types[] = new LuminousSimpleRule(3, 'MAKE_DEP', LUMINOUS_REGEX,
    '/(^[[:alnum:]_\-\. ]+?:)(.*?$)/m', null, 2);
      
//     // Makefile make Rule.
    $this->simple_types[] = 
      new LuminousSimpleRule(3, 'MAKE_TARGET', LUMINOUS_REGEX, 
        '/^[[:alnum:]_\-\. \t]+?(?=:)/m');
    parent::__construct();
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoVersion('0.25.00');
        
  }
  
  
}





class LuminousGrammarPlain extends LuminousGrammar
{
  
  function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
                         'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('plain');
    $this->SetInfoVersion('0.25.00');      
    
    $this->simple_types = array(
      new LuminousSimpleRule(0, 'COMMENT', LUMINOUS_REGEX,
      '/^[\s]*[#;].*$/m'),

      new LuminousSimpleRule(3, 'VALUE', LUMINOUS_REGEX,
      '/(^[[:alnum:]_ \t]+?=)(.*)/m', null, 2),
      new LuminousSimpleRule(2, 'KEYWORD', LUMINOUS_REGEX,
      '/^[[:alnum:]_ \t]*?(?=[=])/m')      
      );
  }
}

class LuminousGrammarMATLAB extends LuminousGrammar
{

  public $keywords = array('break', 'case', 'catch', 'classdef', 'continue',
    'else', 'elseif','end', 'for', 'function', 'global', 'if', 'otherwise', 
    'parfor', 'persistent', 'return', 'spmd', 'switch', 'try', 'while');
    
  public function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('matlab');
    $this->SetInfoVersion('0.25.00');    
    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule(0, 'COMMENT', LUMINOUS_COMPLETE|LUMINOUS_REGEX,
      '/%\{ (.*? (?R)* .*?)* \}%/sx'),
//       luminous_generic_comment( "%{", "}%"),
      luminous_generic_comment( "%", "\n")
      ,
      new LuminousDelimiterRule(0, 'STRING', LUMINOUS_COMPLETE|LUMINOUS_REGEX,
      $regex = "/
      (?<![a-zA-Z0-9\)\]\}_])
      '
      .*?
      (?<!')
      '
      (?!')
      /sx", null, 'luminous_type_callback_sql_single_quotes')
      );
    
    $this->SetSimpleTypeRules();    
    
  }
}


class LuminousGrammarCSharp extends LuminousGrammar
{
  public $keywords = array("abstract", "event", "new", "struct", "as", 
    "explicit", "null", "switch", "base", "extern", "object", "this", "false", 
    "operator", "throw", "break", "finally", "out", "true","fixed", "override", 
    "try", "case", "params", "typeof", "catch", "for", "private", "foreach", 
    "protected", "checked", "goto", "public", "unchecked", "class", "if", 
    "readonly", "unsafe", "implicit", "ref", "continue", "in", "return", 
    "using", "decimal", "virtual", "default", "interface", "sealed", "volatile",
    "delegate", "internal", "void", "do", "is", "sizeof", "while", "lock", 
    "stackalloc", "else", "long", "static", "enum", "namespace");
  
  public $types = array("bool", "byte", "char", "const", "double", "float", "int",
  "long", "sbyte", "short", "uint", "ulong", "ushort", "string",
  // system namespace
  "Array", "Attribute", "Byte", "Buffer", "Char", "DateTime", "Double", "EventArgs",
  "EventHandler", "Exception", "U?Int(?:16|32|64|Ptr)", "Object", "String", "Tuple",
  "Type",
  // system.collection namespace
  "ArrayList", "I?Comparer", "I?Dictionary", "Hashtable", "Hashset", "I?List", 
  "I?Set", "Queue", "SortedList", "Stack"
  );
  public $oo_separators = array('\.');
  
 function __construct()
  {
    
    
    $this->SetInfoAuthor( 
      array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
      'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('cs');
    $this->SetInfoVersion('0.25.00');    
    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule(0, 'PREPROCESSOR', LUMINOUS_REGEX|LUMINOUS_COMPLETE,
      '/#.*?[^\\\](\\\\)*$/sm'),
      luminous_generic_doc_comment('/**', '*/'),
      luminous_generic_doc_comment('/*!', '*/'),
      luminous_generic_doc_comment('//!', "\n"),
      luminous_generic_doc_comment('///', "\n"),
      
      luminous_generic_comment('/*', '*/'),
      luminous_generic_comment('//', "\n"),
      luminous_generic_string(),
      
      new LuminousDelimiterRule(0, 'CHARACTER', 0, '\'', '\'',
      'luminous_type_callback_cstring'),
    );
    
    $this->SetSimpleTypeRules();
    $this->simple_types[] = luminous_generic_constant();
    
  }

}


class LuminousGrammarJava extends LuminousGrammar
{
  public $keywords = array("abstract", "continue", "for", "new", "switch",
"assert", "default", "goto", "package", "synchronized",
"do", "if", "private", "this",
"break", "implements", "protected", "throw",
"else", "import", "public", "throws",
"case", "enum", "instanceof", "return", "transient",
"catch", "extends", "try",
"final", "interface", "static", "void",
"class", "finally", "strictfp", "volatile",
"float", "native", "super", "while");

  public $types = array("byte", "const", "char", "double", "float", "int",
  "short", "long", "bool(ean)?", "String", "Boolean", "Byte", "Character", "Class",
  "Double", "Float", "Integer", "Long", "Number", "Object", "Package", 
  "Short", "StringBuffer", "Thread", "Void", "Exception",
  "Abstract(?:Collection|List|Map|SequentialList|Set)",
  "Array(?:List|s)",
  "BitSet",
  "Calendar",
  "Collections",
  "Currency",
  "Date",
  "Dictionary",
  "EventListenerProxy",
  "EventObject",
  "GregorianCalendar",
  "Hash(?:Map|Set|table)",
  "IdentityHashMap",
  "Linked(?:Hash(?:Map|Set)|List)",
  "ListResourceBundle",
  "Locale",
  "Observable",
  "Properties",
  "Property(?:Permission|ResourceBundle)",
  "Random",
  "ResourceBundle",
  "SimpleTimeZone",
  "Stack",
  "StringTokenizer",
  "Timer(?:Task)?",
  "TimeZone",
  "Tree(?:Map|Set)",
  "Vector",
  "WeakHashMap"
  
  );
  public $oo_separators = array('\.');
  function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('java');
    $this->SetInfoVersion('0.25.00');        
    
    $this->delimited_types = array(
      
      luminous_generic_doc_comment('/**', '*/'),
      
      luminous_generic_comment('/*', '*/'),
      luminous_generic_comment('//', "\n"),
      
      luminous_generic_string(),
      
      new LuminousDelimiterRule(0, 'CHARACTER', 0, '\'', '\'',
      'luminous_type_callback_cstring')      
      
      );
    $this->SetSimpleTypeRules();
    $this->simple_types[] = luminous_generic_constant();
    
      
  }
}


/** Normal Diff */
class LuminousGrammarDiff extends LuminousGrammar
{

  
  function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('diff');
    $this->SetInfoVersion('0.25.00');        
    
    $this->simple_types = array(
      new LuminousSimpleRule(1, 'DIFF_RANGE', LUMINOUS_REGEX, 
        '/^[0-9]+(?:,[0-9]+)?[acd]?[0-9]+(,[0-9]+)?$/mi'),
      new LuminousSimpleRule(0, 'DIFF_OLD', LUMINOUS_REGEX,
        '/^&lt;.*$/mi'),
      new LuminousSimpleRule(0, 'DIFF_NEW', LUMINOUS_REGEX,
        '/^\&gt;.*$/mi')
    );
    
  }
}


/** Unified Diff */
class LuminousGrammarUDiff extends LuminousGrammar
{

  
  function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('udiff');
    $this->SetInfoVersion('0.25.00');        
    
    $this->simple_types = array(
      new LuminousSimpleRule(1, 'DIFF_HEADER_NEW', LUMINOUS_REGEX,
        '/^\+{3}.*$/mi'),
        
      new LuminousSimpleRule(1, 'DIFF_HEADER_OLD', LUMINOUS_REGEX,
       '/^\-{3}.*$/mi'),        
        
      new LuminousSimpleRule(1, 'DIFF_RANGE', LUMINOUS_REGEX, 
        '/^@@.*@@$/mi'),
        
      new LuminousSimpleRule(0, 'DIFF_OLD', LUMINOUS_REGEX,
        '/^\-[^\-].*$/mi'),
        
      new LuminousSimpleRule(0, 'DIFF_NEW', LUMINOUS_REGEX,
       '/^\+[^\+].*$/mi')
    );
    
  }  
}


class LuminousGrammarHaskell extends LuminousGrammar
{

  public $keywords = array("as", "case", "of", "class", "data", "family",
    "instance", "default", "deriving", "do", "forall", "foreign", "hiding",
    "if", "then", "else", "import", "infix", "infixl", "infixr", "let", "in",
    "mdo", "module", "newtype", "proc", "qualified", "rec", "type", "where");
    
  public $types = array("Integer", "Char", "String", "Float");
  
  // Haskell's philosophy seems to be "you've got all those keys on your
  // keyboard and I'm not going to waste them"
  public $operators = array('\+', '\*', '-', '\/', '=', '&gt;', '&lt;', '=',
  '!', '%', '&amp;', '\|', '~', '\^', '\[', '\]', '\(', '\)', '\.', ':', '@'
  );
  
  public function __construct()
  {
    
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('hs');
    $this->SetInfoVersion('0.25.00');        
    
    
    
    $this->delimited_types = array(
      luminous_generic_string('"', '"'),
      new LuminousDelimiterRule(0, "CHARACTER", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
        "/'(\\\\)?.'/"),
      new LuminousDelimiterRule(0, "FUNCTION", 0, "`", "`"),
      new LuminousDelimiterRule(0, "FUNCTION", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
      "/\\\\.*?[\s]/"),
      luminous_generic_comment('--', "\n"),
      
      new LuminousDelimiterRule(0, "COMMENT", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
      '/\{- ( .*? (?R)* .*?)* -\}/sx'
      // old code.
//       // Haskell's comments can be nested which is all very nice but 
//       // I think that it's computationally impossible to validate arbtrary 
//       // depth bracket nesting with a regex.
//       // This one goes to depth 2.
//       "/
//       \{\-
//         (?:.*?
//         (?:\{\-.*?\-\})?
//         )*?
//       \-\}
//       /xs"
      )
      );    
      
    $this->SetSimpleTypeRules();  
  }
  
}




class LuminousGrammarSQL extends LuminousGrammar
{
  
  public $keyword_regex =  "/(?<![a-zA-Z0-9_$])%KEYWORD(?![a-zA-Z0-9_])/i";
  public $keywords = array("ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER",
  "ANALYZE", "AND", "AS", "ASC", "ATTACH", "AUTO(?:_)?INCREMENT", "BEFORE", "BEGIN",
  "BETWEEN", "BY", "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN",
  "COMMIT", "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
  "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
  "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", "ELSE",
  "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", "FAIL", "FOR",
  "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", "IGNORE",
  "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", "INSERT",
  "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", "LEFT",
  "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", "NULL", "OF",
  "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", "PRIMARY", "QUERY",
  "RAISE", "REFERENCES", "REGEXP", "REINDEX", "RELEASE", "RENAME", "REPLACE",
  "RESTRICT", "RIGHT", "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE",
  "TEMP", "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
  "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE");
  
  public $type_regex =  "/(?<![a-zA-Z0-9_$])(:?%TYPE)(?![a-zA-Z0-9_])/i";
  
  public $types = array("(?:tiny|small|medium|big)?int(?:eger)?", "(?:var)?char",
  "(?:tiny|medium|long)?text", "(?:long)?blob", "float", "double", "decimal", 
  "data(?:time)?", "time(?:stamp)?");
  
  
  public function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('sql');
    $this->SetInfoVersion('0.25.00');        
    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule(0, "COMMENT", 0, "--", "\n"),
//       new LuminousDelimiterRule("STRING", 0, '\'', '\''), 
        
      new LuminousDelimiterRule(0, "STRING", LUMINOUS_REGEX|LUMINOUS_COMPLETE, 
        "/
        (?:'')
        |
        (?:(?:'.*?(?<!')')(?!'))
        /sx", null, 'luminous_type_callback_sql_single_quotes'),
      new LuminousDelimiterRule(0, "STRING", 0, "`", "`",
        'luminous_type_callback_generic_string'),
      new LuminousDelimiterRule(0, "STRING", 0, '"', '"',
        'luminous_type_callback_generic_string')
      );
      
    $this->SetSimpleTypeRules();
    
    
  }

}

///\todo: named operators.
///\todo: variable interpolation
class LuminousGrammarPerl extends LuminousGrammar
{
  public $keywords = array("my", "print",
     "caller",
     "continue",
     "die",
     "do",
     "dump",
     "else",
     "elsif",
     "eval",
     "exit",
     "for",
     "foreach",
     "goto",
     "import",
     "if",
     "last",
     "local",
     "next",
     "prototype",
     "redo",
     "return",
     "sub",
     "use",
     "wantarray",
     "while");
 
  public $ignore_outside_strict = false;
  
  public $oo_separators = array('::', '-&gt;');
  
  
  
  public function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('pl');
    $this->SetInfoVersion('0.25.00');   
    
    
    
    $this->delimited_types = array(
      new LuminousDelimiterRule(0, 'SHEBANG', LUMINOUS_REGEX|LUMINOUS_COMPLETE, 
      "/^[\s]*#!.*?\n/"),
      new LuminousDelimiterRule(0, "FUNCTION", 0, '`', '`'),
      new LuminousDelimiterRule(0, "COMMENT", LUMINOUS_REGEX|LUMINOUS_COMPLETE, 
      '/(?<![%@\$])#.*/', null),
      new LuminousDelimiterRule(0, "STRING", LUMINOUS_EXCLUDE, '"', '"',
      'luminous_type_callback_perl_string'),
      new LuminousDelimiterRule(0, "STRING", LUMINOUS_EXCLUDE, '\'', '\''),
      
      new LuminousDelimiterRule(0, "STRING",       
        LUMINOUS_REGEX|LUMINOUS_DYNAMIC_DELIMS|LUMINOUS_COMPLETE|LUMINOUS_EXCLUDE,
        '/(?<![a-zA-Z0-9_\$])q[qxw]?[\s]*(?![a-zA-Z0-9])/',
        null, 'luminous_type_callback_perl_string'),
        new LuminousDelimiterRule(0, "VALUE", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
       "/&lt;(STDIN|STDOUT|STDERR|DATA)&gt;/"),
       
       // I don't know if these next two are right.
       new LuminousDelimiterRule(0, "REGEX", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
        '/
          (?<=([\(\[,=:;\?!~]))
          [\s]* 
          (?:m|qr)?\/
            (?:.*?[^\\\])*?
          (?:\\\\\\\\)*\/
          [cgimosx]*/x', null, 'luminous_type_callback_generic_string'),        
      
          new LuminousDelimiterRule(0, "REGEX", LUMINOUS_REGEX|LUMINOUS_COMPLETE,
        '/
          (?<=([\(\[,=:;\?!~]))
          [\s]* 
          (?:s|tr|y)\/
            (?:(.*?[^\\\])*?
          (?:\\\\\\\\)*\/){2}
          [cdsegimosx]*/x',       
        null, 'luminous_type_callback_generic_string'),
        
        new LuminousDelimiterRule(0, 'HEREDOC', 
          LUMINOUS_COMPLETE|LUMINOUS_REGEX|LUMINOUS_DYNAMIC_DELIMS,
          '/(?:&lt;){2}["`]?(?=[[:alnum:]])/', null,
          'luminous_type_callback_perl_string'),
          
        new LuminousDelimiterRule(0, 'HEREDOC', 
          LUMINOUS_COMPLETE|LUMINOUS_REGEX|LUMINOUS_DYNAMIC_DELIMS,
          '/(?:&lt;){2}[\']?(?=[[:alnum:]])/')          
       );       

    $this->ignore_outside = array( 
      new LuminousBoundaryRule(LUMINOUS_REGEX, "/^/", 
      "/__(DATA|END)__/")
      );
      
      
      // this isn't really a type, but what else do you call it?
      $this->simple_types[] = new LuminousSimpleRule(3, 'TYPE',
        LUMINOUS_REGEX, '/&lt;[[:alnum:]_]+&gt;/');
      
      
      $this->simple_types[] = new LuminousSimpleRule(3, 'VARIABLE',
        LUMINOUS_REGEX, "/(?!<[a-z0-9_])[$%@][a-z0-9_]+/i");
        
/*      $this->simple_types[] = new LuminousSimpleRule(3, 'VALUE',
        LUMINOUS_REGEX, "/(?<=::)(?>[a-z0-9_]+)[\s]*(?!\()/i");      */  
      
      
      $this->SetSimpleTypeRules();
      $this->simple_types[] = luminous_generic_constant();
      
        

      $this->simple_types[] = new LuminousSimpleRule(3, 'VALUE',
        LUMINOUS_REGEX, "/__(DATA|END)__/");  
        
  }
  

}

class LuminousGrammarPHP extends LuminousGrammar
{

  public $operators = array('\+', '\*', '-', '\/', '=', '&gt;', 
    '&lt;', '=', '!', '%', '&amp;', '\|', '~', '\^', '\[', '\]');
  
//   public $keywords = array(
//   "&lt;\?(?:php)?", "\?&gt;",
//   "abstract", "and",  "as", "break",
//   "case", "catch", "cfunction", "class", "Class", "clone",
//   "const", "continue", "declare", "default", "do",
//   "echo","else", "elseif", "enddeclare", "endfor", "endforeach",
//   "endif", "endswitch", "endwhile", "extends", "final",
//   "for", "foreach", "function", "global", "goto",
//   "if", "implements", "interface", "instanceof",
//   "namespace", "new", "old_function", "or", "private",
//   "protected", "public", "return", "static", "switch", "throw",
//   "try", "use", "var", "while", "xor" );
  
  
  public $keywords = array("&lt;\?(?:php)?", "\?&gt;", 'Class', 'a(?:(?:bstract)|(?:nd)|(?:s))', 'break', 'c(?:(?:a(?:(?:se)|(?:tch)))|(?:function)|(?:l(?:(?:ass)|(?:one)))|(?:on(?:(?:st)|(?:tinue))))', 'd(?:(?:e(?:(?:clare)|(?:fault)))|(?:o))', 'e(?:(?:cho)|(?:lseif)|(?:nd(?:(?:declare)|(?:foreach)|(?:if)|(?:switch)|(?:while)))|(?:xtends))', 'f(?:(?:inal)|(?:oreach)|(?:unction))', 'g(?:(?:lobal)|(?:oto))', 'i(?:(?:f)|(?:mplements)|(?:n(?:(?:stanceof)|(?:terface))))', 'n(?:(?:amespace)|(?:ew))', 'o(?:(?:ld_function)|(?:r))', 'p(?:(?:r(?:(?:ivate)|(?:otected)))|(?:ublic))', 'return', 's(?:(?:tatic)|(?:witch))', 't(?:(?:hrow)|(?:ry))', 'use', 'var', 'while', 'xor',
  '\$this', 'parent');
    

  public $function_regex =  '/(?<![a-zA-Z0-9_$])(?:%FUNCTION)(?![a-zA-Z0-9_])/x';     
  public $functions = array("include(?:_once)?", "require(?:_once)?",
    // array functions
    'array(_
    (?:(?:change_key_case)|
    (?:chunk)|
    (?:combine)|
    (?:count_values)|
    (?:diff(?:_(?:u?assoc|u?key))?)|
    (?:fill(?:_keys)?)|
    (?:filter)|
    (?:flip)|
    (?:intersect(?:_(?:u?assoc|u?key))?)|
    (?:key(?:s|_exists))|
    (?:map)|
    (?:merge(?:_recursive)?)|
    (?:multisort)|
    (?:pad)|
    (?:pop)|
    (?:product)|
    (?:push)|
    (?:rand)|
    (?:reduce)|
    (?:replace(?:_recursive)?)|
    (?:reverse)|
    (?:search)|
    (?:shift)|
    (?:slice)|
    (?:splice)|
    (?:sum)|
    (?:udiff(?:_u?assoc)?)|
    (?:uintersect(?:_u?assoc)?)|
    (?:unique)|
    (?:unshift)|
    (?:values)|
    (?:walk(?:_recursive)?)
    ))?',
    // pcre functions
    'preg_(?:
    filter|
    grep|
    last_error|
    match(?:_all)?|
    quote|
    replace(?:_callback)?|
    split)',
    // magic methods
    '__(?:
    construct|destruct|call|callStatic|get|set|isset|unset|sleep|wakeup|toString|invoke|set_state|clone)'
    );
    
  public $types = array('false', 'null', 'true');
  public $oo_separators = array('::', '-&gt;');
  
  public function __construct()
  {
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('php');
    $this->SetInfoVersion('0.25.00');    
    
    // I think the close tag is optional.
    $this->ignore_outside =  array(
      new LuminousBoundaryRule(LUMINOUS_REGEX, 
    "/&lt;\?(php)?/", "/(\?&gt;|$)/")
    );
  
    
    $this->delimited_types = array(
      new LuminousDelimiterRule(0, "DOCCOMMENT", 0, "/**", "*/",
        'luminous_type_callback_doccomment'),
      new LuminousDelimiterRule(0, "DOCCOMMENT", 0, "///", "\n",
        'luminous_type_callback_doccomment'),        
      new LuminousDelimiterRule(0, "COMMENT", 0, "/*", "*/",
        'luminous_type_callback_comment'),
      new LuminousDelimiterRule(0, "COMMENT", LUMINOUS_STOP_AT_END, "//", "\n",
        'luminous_type_callback_comment'),
      new LuminousDelimiterRule(0, "COMMENT", LUMINOUS_STOP_AT_END, "#", "\n",
        'luminous_type_callback_comment'),
      new LuminousDelimiterRule(0, "STRING", 0, "'", "'",
        'luminous_type_callback_php_sstring'),
        
      new LuminousDelimiterRule(0, "STRING", 0, '"', '"',
      'luminous_type_callback_php_dstring'),
      
      new LuminousDelimiterRule(0, "HEREDOC", 
        LUMINOUS_REGEX|LUMINOUS_DYNAMIC_DELIMS|LUMINOUS_COMPLETE, 
        '/(&lt;){3}[\s]*["\']?[\s]*/', null, 
        'luminous_type_callback_php_dstring')    
    );
    $this->child_grammar = new LuminousGrammarJavaScriptEmbedded();
    
    $this->SetSimpleTypeRules();
    $this->simple_types[] = new LuminousSimpleRule(3, 'VARIABLE', LUMINOUS_REGEX, 
    "/\\$[a-z_][a-z0-9_]*/i");
    $this->simple_types[] = luminous_generic_constant();
    
  }
  
}




class LuminousGrammarVisualBasic extends LuminousGrammar 
{
  
  
  public $operators = array("\+", "\-", "&amp;", "=", "\*", "\^", "\/",  
  "(?<![a-z0-9])and(also?)(?![a-z0-9])", "(?<![a-z0-9])or(else)?(?![a-z0-9])",
  '(?<![a-z0-9])not(?![a-z0-9])', '(?<![a-z0-9])xor(?![a-z0-9])'
  );


  public $types = array(
    "boolean",
    "byte",
    "c(?:bool|byte|char|date|dec|dbl|int|lng|obj|short|sng|str|type)",
    "char",
    "date",
    "decimal",
    "double",
    "enum",
    "false",
    "integer",
    "long",
    "short",
    "string",
    "true");
    
  // HOW MANY?
  public $keywords = array(
    "addhandler", "addressof", "alias", "ansi", "as", "assembly", "auto",
    "byref", "byval", "call", "case", "catch", "const", "declare", "default",
    "delegate", "dim", "directcast", "do", "each", "else(?:if)?", "end", "erase",
    "error", "event", "exit", "finally", "for", "friend", "function", 
    "get(?:type)?", "gosub", "goto", "handles", "if", "implements", "interface",
    "let", "Lib", "like", "loop", "me", "mod", "module", "mustinheret", 
    "mustoverride", "mybase", "myclass", "namespace", "new", "next", "nothing",
    "on", "option", "optional", "overloads", "overridable", "overrides",
    "paramarray", "preserve", "private", "property", "protected", "public", 
    "raiseevent", "readonly", "return", "select", "set", "shadows", "shared",
    "single", "static", "step", "stop", "structure", "sub", "synclock", "then",
    "throw", "to", "try", "typeof", "unicode", "until", "variant", "when", 
    "while", "with", "withevents", "writeonly"
  );
  
  
  
  public $escape_chars = array();
  
  

  public function __construct()
  {
    $this->case_insensitive = true;
    
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('vb');
    $this->SetInfoVersion('0.25.00');        
    
    $this->delimited_types = array(
      new LuminousDelimiterRule(0, "DOCCOMMENT", 0, "'''", "\n"),
      new LuminousDelimiterRule(0, "COMMENT", 0, "'", "\n"),
      new LuminousDelimiterRule(0, "STRING", 0, '"', '"'),
      new LuminousDelimiterRule(0, "PREPROCESSOR", 
        LUMINOUS_REGEX|LUMINOUS_COMPLETE, "/^#.*?(?=($|\"))/m")
    );
    
    $this->SetSimpleTypeRules();
    
    $this->simple_types[] =  new LuminousSimpleRule(3, 'CONSTANT', LUMINOUS_REGEX,
    '/(?<![[:alnum:]_&<])(?-i:\b[A-Z_][A-Z0-9_]{2,})(?![[:alnum:]_])/');
    
  }
  
}


class LuminousGrammarWhitespace extends LuminousGrammar
{
  public function __construct()
  {
    $this->SetInfoAuthor( 
    array('name'=>'Mark Watkinson', 'email'=>'markwatkinson@gmail.com',
    'website'=>'http://www.asgaard.co.uk'));
    $this->SetInfoLanguage('whitespace');
    $this->SetInfoVersion('0.25.00');
    $this->simple_types[] = 
      new LuminousSimpleRule(0, 'COMMENT', LUMINOUS_REGEX, '/[^\s]+/');
    $this->simple_types[] = 
      new LuminousSimpleRule(0, 'WHITESPACE_SPACE', 0, ' ');
    $this->simple_types[] = 
      new LuminousSimpleRule(0, 'WHITESPACE_TAB', 0, "\t");
  }
  
}

/// \endcond

?>
